/*	Renegade Scripts.dll
	SSGM CTF scripts and functions
	Copyright 2007 Vloktboky, Whitedragon(MDB), Jonathan Wilson

	This file is part of the Renegade scripts.dll
	The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
	the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2, or (at your option) any later
	version. See the file COPYING for more details.
	In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
	Only the source code to the module(s) containing the licenced code has to be released.
*/

#include <stdarg.h>
#include "scripts.h"
#include "engine.h"
#include "gmmain.h"

GameObject *CTFController = 0;

//Models for the flag status icon
char *CTFIcons[4][2] = {
	//{Model,Animation},
	{"",""},
	{"O_EM_CHEVRON", "O_EM_CHEVRON.O_EM_CHEVRON"}, //Flag on the ped
	{"O_EM_REDARR","O_EM_REDARR.O_EM_REDARR"}, //Flag carried by enemy player
	{"O_EM_GRNARR","O_EM_GRNARR.O_EM_GRNARR"} //Flag on the ground
};

//Animations for when the flag is captured
char *CTFAnimations[12] = {
	"H_A_SIDEKICK","H_A_PUNCHCOMBO","H_A_A0A0_L02","H_A_J22C","H_A_A0A0_L23",
	"H_A_A0A0_L58","H_A_B0A0_L05","H_A_A0A0_L12","H_A_J14C","H_A_X33C",
	"H_A_A0A0_L22","H_A_A0A0_L24"
};

//Team specific sounds to play for flag events
char *CTFTeamSounds[6][2] = {
	//{Nod,GDI},
	{"",""},
	{"MXXDSGN_DSGN0011I1EVAN_SND.wav","MXXDSGN_DSGN0001I1EVAG_SND.wav"}, //Steal
	{"",""}, //Drop
	{"",""}, //Pick up
	{"MXXDSGN_DSGN0044I1EVAN_SND.wav","MXXDSGN_DSGN0014I1EVAG_SND.wav"}, //Return
	{"MXXDSGN_DSGN0012I1EVAG_SND.wav","MXXDSGN_DSGN0042I1EVAN_SND.wav"}, //Capture
};

//Sounds to play for flag events
char *CTFSounds[5] = {
	"",
	"pickupflag.wav", //Steal and pick up
	"dropflag.wav", //Drop
	"levelchange.wav", //Return
	"capflag.wav" //Capture
};


void CTFSettings::Load() {
	if (Settings->GameMode == 2) {
		LoadInt(CTFCapLimit,"CaptureLimit",3,true,true,false);
		LoadVector3(CTFFlagOffset,"FlagOffset");
		LoadBool(CTFRegenForHolder,"EnableRegenForHolder");
		LoadFloat(CTFRegenAmount,"RegenAmount",2.0);
		LoadSString(CTFFlagPreset,"FlagPresetName","POW_Data_Disc");
		LoadSString(CTFFlagModel[0],"FlagModelName0","o_flag");
		LoadSString(CTFFlagModel[1],"FlagModelName1","o_flag");
		LoadSString(CTFFlagBackPreset,"CarriedFlagPresetName","CtfFlag");
		LoadSString(CTFPedPreset[0],"PedestalPresetName0","CtfPedestalRed");
		LoadSString(CTFPedPreset[1],"PedestalPresetName1","CtfPedestalGold");
		LoadFloat(CTFCapPoints,"CapturePoints",0);
		LoadFloat(CTFCapPointsTeam,"CapturePointsTeam",0);
		LoadFloat(CTFCapMoney,"CaptureMoney",0);
		LoadFloat(CTFCapMoneyTeam,"CaptureMoneyTeam",0);
		LoadFloat(CTFReturnTime,"ReturnDropFlagTime",120);
		LoadBool(CTFFriendlyFlagRadar,"ShowFriendlyFlagRadar");
		LoadBool(CTFEnemyFlagRadar,"ShowEnemyFlagRadar");
		LoadBool(CTFEnableReverse,"EnableReverseCTF");

		int C4ID = Get_Definition_ID("CnC_POW_MineRemote_02");
		WeaponDefinitionClass *Def = Get_Weapon_Definition(Get_Powerup_Weapon("CnC_POW_MineRemote_02"));
		if (C4ID && Def && !Settings->DisableBeacons && !Data->Mod) {
			Def->CanRecieveGenericCnCAmmo = false;
			Set_Beacon(0,300,C4ID,Def->IconNameID,Def->HUDIconTextureName.Peek_Buffer()); //"hud_remotec4.tga");
			Set_Beacon(1,300,C4ID,Def->IconNameID,Def->HUDIconTextureName.Peek_Buffer());
		}
		else {
			Set_Beacon(0,0,0,0,"");
			Set_Beacon(1,0,0,0,"");
		}
		//Update_PT_Data();

		int Class = 0;
		LoadInt(Class,"ForceClass",0,true,true,false);
		if (!Class) {
			std::vector<int> Classes;
			for (int z = 1; ; ++z) {
				std::string Value;
				LoadSString(Value,StrFormat("CTF_C%02d_Name",z).c_str(),"NULL",false,true,false);
				if (Value == "NULL") {
					break;
				}
				bool Enabled,Reverse;
				LoadBool(Enabled,StrFormat("CTF_C%02d_Enabled",z).c_str(),true,false,true,false);
				LoadBool(Reverse,StrFormat("CTF_C%02d_Reverse",z).c_str(),false,false,true,false);

				if (Enabled) {
					if (Reverse) {
						if (CTFEnableReverse) {
							Classes.push_back(z);
						}
					}
					else {
						Classes.push_back(z);
					}
				}
			}

			if (Classes.empty()) {
				FDSMessage("Critical Error! No CTF coordinates were found. Exiting FDS.","_ERROR");
#ifdef WIN32
				MessageBox(HWND_DESKTOP,"No CTF coordinates found!","Critical SSGM Error",MB_OK|MB_ICONEXCLAMATION);
#endif
				exit(1);
			}
			else {
				Class = Classes[Commands->Get_Random_Int(0,Classes.size())];
			}
		}

		CTFClass = Class;

		LoadSString(CTFClassName,StrFormat("CTF_C%02d_Name",CTFClass).c_str(),"NULL",false,true,false);
		LoadBool(CTFReverse,StrFormat("CTF_C%02d_Reverse",CTFClass).c_str(),false,false,true,false);
		LoadInt(CTFCapLimit,StrFormat("CTF_C%02d_CaptureLimit",CTFClass).c_str(),CTFCapLimit,false,true,false);
		LoadVector3(CTFPedPos[0],StrFormat("CTF_C%02d_Team0",CTFClass).c_str(),Vector3(0.0f,0.0f,0.0f),false,true,false);
		LoadVector3(CTFPedPos[1],StrFormat("CTF_C%02d_Team1",CTFClass).c_str(),Vector3(0.0f,0.0f,0.0f),false,true,false);
	}
}


//******************************************************************************
//******************************* CTF FUNCTIONS ********************************
//******************************************************************************

//Sets the location of the flag and changes the icon to match
void Set_Flag_Location(int Team, int Loc) {
	if (Team > 1 || Team < 0 || Loc > 3 || Loc < 1) {
		return;
	}

	Data->CTFFlagLoc[Team] = Loc;

	GameObject *Icon = Commands->Find_Object(Data->CTFFlagIcon[Team]);
	Commands->Set_Model(Icon,CTFIcons[Loc][0]);
	Commands->Set_Animation(Icon,CTFIcons[Loc][1],true,0,0.0f,-1.0f,false);
}

//Creates the flag at position X, used for dead flag holder
GameObject *Create_CTF_DropFlag(int Team, Vector3 Position) {
	if (Team > 1 || Team < 0) {
		return 0;
	}

	Data->CTFFlagHolder[Team] = 0;
	Data->CTFFlagAttached[Team][0] = 0;
	Data->CTFFlagAttached[Team][1] = 0;

	Vector3 FlagLoc = Position;
	FlagLoc += Settings->CTFFlagOffset;
	GameObject *Flag = Commands->Create_Object(Settings->CTFFlagPreset.c_str(),FlagLoc);
	Commands->Set_Player_Type(Flag,Team);
	Commands->Set_Model(Flag,Settings->CTFFlagModel[Team].c_str());
	Commands->Attach_Script(Flag,"MDB_SSGM_CTF_DropFlag","");
	Commands->Attach_Script(Flag,"KAK_Prevent_Kill","");

	Set_Flag_Location(Team,3);

	return Flag;
}

//Creates the flag at Team's Ped
GameObject *Create_CTF_PedFlag(int Team) {
	if (Team > 1 || Team < 0) {
		return 0;
	}

	Data->CTFFlagHolder[Team] = 0;
	Data->CTFFlagAttached[Team][0] = 0;
	Data->CTFFlagAttached[Team][1] = 0;

	Vector3 FlagLoc = Settings->CTFPedPos[Team];
	FlagLoc += Settings->CTFFlagOffset;
	GameObject *Flag = Commands->Create_Object(Settings->CTFFlagPreset.c_str(),FlagLoc);
	Commands->Set_Player_Type(Flag,Team);
	Commands->Set_Model(Flag,Settings->CTFFlagModel[Team].c_str());
	Commands->Attach_Script(Flag,"MDB_SSGM_CTF_Flag","");
	Commands->Attach_Script(Flag,"KAK_Prevent_Kill","");

	Set_Flag_Location(Team,1);

	return Flag;
}

//Creates Team's CTF Ped and icon
GameObject *Create_CTF_Pedestal(int Team) {
	if (Team > 1 || Team < 0) {
		return 0;
	}

	Vector3 PedPos = Settings->CTFPedPos[Team];
	GameObject *Ped = Commands->Create_Object(Settings->CTFPedPreset[Team].c_str(),PedPos);
	Commands->Set_Player_Type(Ped,Team);
	Commands->Attach_Script(Ped,"KAK_Prevent_Kill","");
	Create_CTF_PedFlag(Team);

	PedPos.Z += Settings->CTFFlagOffset.Z;
	PedPos.Z += 1.25f;
	GameObject *Icon = Commands->Create_Object("Invisible_Object",PedPos);
	Data->CTFFlagIcon[Team] = Commands->Get_ID(Icon);

	return Ped;
}


void CTF_Level_Loaded() {
	Commands->Attach_Script(Create_CTF_Pedestal(0),"MDB_SSGM_CTF_Announcement","");
	Create_CTF_Pedestal(1);
	Set_Flag_Location(0,1);
	Set_Flag_Location(1,1);
}


void CTF_GameOver() {
	Data->CTFFlagHolder[0] = 0;
	Data->CTFFlagHolder[1] = 0;
	Data->CTFFlagAttached[0][0] = 0;
	Data->CTFFlagAttached[0][1] = 0;
	Data->CTFFlagAttached[1][0] = 0;
	Data->CTFFlagAttached[1][1] = 0;
	Data->CTFCaps[0] = 0;
	Data->CTFCaps[1] = 0;
}

void CTF_Player_Join(int ID) {
	Commands->Send_Custom_Event(0,CTFController,983294,ID,1.0f);
}

void CTF_ObjectHook(GameObject *obj) {
	if (Commands->Is_A_Star(obj)) {
		if (Data->CTFFlagHolder[PTTEAM(Get_Object_Type(obj))] == Commands->Get_ID(obj)) {
			Attach_Script_Once(obj,"MDB_SSGM_CTF_FlagHolder","");
		}
	}
}

//Handles all CTF messages
void CTF_Message(int Type, int Team, GameObject *Player1, GameObject *Player2) {
	if (Type == 1) { //Flag stolen
		std::string Msg;
		StrFormat2(Msg,"%ls has stolen the %ls flag!",Get_Wide_Player_Name(Player1),Get_Wide_Team_Name(Team));
		FDSMessage(Msg,"_CTF");
		Console_Input(StrFormat("msg %s",Msg.c_str()).c_str());
		Commands->Create_2D_WAV_Sound(CTFTeamSounds[1][Team]);
		Commands->Create_2D_WAV_Sound(CTFSounds[1]);
	}
	else if (Type == 2) { //Flag dropped
		std::string Msg;
		StrFormat2(Msg,"The %ls flag, which was carried by %ls, has been dropped thanks to %ls.",Get_Wide_Team_Name(Team),Get_Wide_Player_Name(Player1),Get_Wide_Player_Name(Player2));
		FDSMessage(Msg,"_CTF");
		Console_Input(StrFormat("msg %s",Msg.c_str()).c_str());
		Commands->Create_2D_WAV_Sound(CTFSounds[2]);
	}
	else if (Type == 3) { //Dropped flag picked back up
		std::string Msg;
		StrFormat2(Msg,"%ls has picked up the %ls flag!",Get_Wide_Player_Name(Player1),Get_Wide_Team_Name(Team));
		FDSMessage(Msg,"_CTF");
		Console_Input(StrFormat("msg %s",Msg.c_str()).c_str());
		Commands->Create_2D_WAV_Sound(CTFSounds[1]);
	}
	else if (Type == 4) { //Flag returned
		std::string Msg;
		StrFormat2(Msg,"%ls returned the %ls flag!",Get_Wide_Player_Name(Player1),Get_Wide_Team_Name(Team));
		FDSMessage(Msg,"_CTF");
		Console_Input(StrFormat("msg %s",Msg.c_str()).c_str());
		Commands->Create_2D_WAV_Sound(CTFTeamSounds[4][Team]);
		Commands->Create_2D_WAV_Sound(CTFSounds[3]);
	}
	else if (Type == 5) { //Flag returned by server
		std::string Msg;
		StrFormat2(Msg,"The %ls flag has been automatically returned by the server.",Get_Wide_Team_Name(Team));
		FDSMessage(Msg,"_CTF");
		Console_Input(StrFormat("msg %s",Msg.c_str()).c_str());
		Commands->Create_2D_WAV_Sound(CTFTeamSounds[4][Team]);
		Commands->Create_2D_WAV_Sound(CTFSounds[3]);
	}
	else if (Type == 6) { //Flag captured
		std::string Msg;
		StrFormat2(Msg,"%ls has captured the %ls flag!",Get_Wide_Player_Name(Player1),Get_Wide_Team_Name(Team));
		FDSMessage(Msg,"_CTF");
		Console_Input(StrFormat("msg %s",Msg.c_str()).c_str());
		if (Settings->CTFCapLimit > 0) {
			if ((Settings->CTFCapLimit - Data->CTFCaps[Get_Object_Type(Player1)]) > 0) {
				StrFormat2(Msg,"%ls needs to capture the %ls flag %d more time(s) to win.",Get_Wide_Team_Name(Get_Object_Type(Player1)),Get_Wide_Team_Name(Team),(Settings->CTFCapLimit - Data->CTFCaps[Get_Object_Type(Player1)]));
				FDSMessage(Msg,"_CTF");
				Console_Input(StrFormat("msg %s",Msg.c_str()).c_str());
			}
			else {
				StrFormat2(Msg,"%ls has won the game by capturing the %ls flag %d time(s)!",Get_Wide_Team_Name(Get_Object_Type(Player1)),Get_Wide_Team_Name(Team),Settings->CTFCapLimit);
				FDSMessage(Msg,"_CTF");
				Console_Input(StrFormat("msg %s",Msg.c_str()).c_str());
			}
		}
		Commands->Create_2D_WAV_Sound(CTFTeamSounds[5][Team]);
		Commands->Create_2D_WAV_Sound(CTFSounds[4]);
	}
}


//******************************************************************************
//**************************** CTF CHAT COMMANDS *******************************
//******************************************************************************

class CapturesChatCommand : public ChatCommandClass {
	void Triggered(int ID,const TokenClass &Text,int ChatType) {
		Console_Input(StrFormat("ppage %d %ls Flag Captures: %d/%d - %ls Flag Captures: %d/%d",ID,Get_Wide_Team_Name(0),Data->CTFCaps[0],Settings->CTFCapLimit,Get_Wide_Team_Name(1),Data->CTFCaps[1],Settings->CTFCapLimit).c_str());
	}
};
ChatCommandRegistrant<CapturesChatCommand> CapturesChatCommandReg("!captures;!caps;!capture;!cap",CHATTYPE_ALL,0,GAMEMODE_CTF);


class FlagInfoChatCommand : public ChatCommandClass {
	void Triggered(int ID,const TokenClass &Text,int ChatType) {
		std::string Msg[2];

		if (Data->CTFFlagLoc[1] == 1) {
			Msg[1] = "currently at its pedestal";
		}
		else if (Data->CTFFlagLoc[1] == 2) {
			StrFormat2(Msg[1],"in %ls's possesion",Get_Wide_Player_Name(Commands->Find_Object(Data->CTFFlagHolder[1])));
		}
		else {
			Msg[1] = "in the field";
		}

		if (Data->CTFFlagLoc[0] == 1) {
			Msg[0] = "currently at its pedestal";
		}
		else if (Data->CTFFlagLoc[0] == 2) {
			StrFormat2(Msg[0],"in %ls's possesion",Get_Wide_Player_Name(Commands->Find_Object(Data->CTFFlagHolder[0])));
		}
		else {
			Msg[0] = "in the field";
		}
	
		Console_Input(StrFormat("ppage %d The %ls flag is %s. The %ls flag is %s. The class is '%s'.",ID,Get_Wide_Team_Name(0),Msg[0].c_str(),Get_Wide_Team_Name(1),Msg[1].c_str(),Settings->CTFClassName.c_str()).c_str());
	}
};
ChatCommandRegistrant<FlagInfoChatCommand> FlagInfoChatCommandReg("!flag;!flaginfo",CHATTYPE_ALL,0,GAMEMODE_CTF);


//******************************************************************************
//**************************** CTF RELATED SCRIPTS *****************************
//******************************************************************************

//Attached to the flag when it's on the pedestal.
void MDB_SSGM_CTF_Flag::NewCreated(GameObject *obj) {
	PickedUp = false;
	int Team = Get_Object_Type(obj);
	if (Settings->CTFFriendlyFlagRadar) {
		GameObject *AttachedFlag = Commands->Create_Object_At_Bone(obj,Settings->CTFFlagBackPreset.c_str(),"Origin");
		Commands->Attach_To_Object_Bone(AttachedFlag, obj,"Origin");
		Commands->Disable_All_Collisions(AttachedFlag);
		Commands->Set_Player_Type(AttachedFlag,Team);
		Commands->Set_Model(AttachedFlag,"null");
		Data->CTFFlagAttached[Team][0] = Commands->Get_ID(AttachedFlag);
	}
	if (Settings->CTFEnemyFlagRadar) {
		GameObject *AttachedFlag2 = Commands->Create_Object_At_Bone(obj,"Invisible_Object","Origin");
		Commands->Attach_To_Object_Bone(AttachedFlag2, obj, "Origin");
		Commands->Disable_All_Collisions(AttachedFlag2);
		Commands->Set_Player_Type(AttachedFlag2,PTTEAM(Team));
		Commands->Set_Model(AttachedFlag2,"null");
		Set_Obj_Radar_Blip_Shape(AttachedFlag2,BLIP_SHAPE_OBJECTIVE);
		Set_Obj_Radar_Blip_Color(AttachedFlag2,Team);
		Data->CTFFlagAttached[Team][1] = Commands->Get_ID(AttachedFlag2);
	}
	Set_Is_Powerup_Persistant(obj,true); //Makes it so the powerup doesn't disappear when a player picks it up, this allows the script to decide when to destroy it
	Set_Powerup_Always_Allow_Grant(obj,true); //Make it so the powerup can always be picked up
	Set_Powerup_Grant_Sound(obj,0); //The grant sound fucks up when a friendly player stands on top of their own flag
}

void MDB_SSGM_CTF_Flag::Custom(GameObject *obj, int message, int param, GameObject *sender) {
	if (message == CUSTOM_EVENT_POWERUP && !PickedUp && Commands->Get_Health(sender) > 0.0f) {
		int Team = Get_Object_Type(obj);
		if (Team != Get_Object_Type(sender)) { //Enemy picked up the flag
			Commands->Attach_Script(sender,"MDB_SSGM_CTF_FlagHolder","");

			Data->CTFFlagHolder[Team] = Commands->Get_ID(sender);	
			CTF_Message(1,Team,sender,0);
			Set_Flag_Location(Team,2);
		
			PickedUp = true;
			Commands->Destroy_Object(obj);
		}
		else { //Friendly picked up the flag (Maybe capture, maybe idiot)
			int OtherTeam = PTTEAM(Team);
			if (Data->CTFFlagHolder[OtherTeam] == Commands->Get_ID(sender)) {	
				Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[OtherTeam][0]));
				Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[OtherTeam][1]));

				Commands->Send_Custom_Event(obj,sender,294829,0,0);

				Data->CTFFlagHolder[OtherTeam] = 0;
				Data->CTFFlagAttached[OtherTeam][0] = 0;
				++Data->CTFCaps[Team];
				CTF_Message(6,OtherTeam,sender,0);	

				Commands->Give_Points(sender,Settings->CTFCapPoints,false);
				Commands->Give_Money(sender,(Settings->CTFCapPoints*-1.0f),false);
				Commands->Give_Points(sender,Settings->CTFCapPointsTeam,true);
				Commands->Give_Money(sender,(Settings->CTFCapPointsTeam*-1.0f),true);
				Commands->Give_Money(sender,Settings->CTFCapMoney,false);	
				Commands->Give_Money(sender,Settings->CTFCapMoneyTeam,true);

				int AnimSize = (sizeof(CTFAnimations)/sizeof(char*));
				int Animation2Play = Commands->Get_Random_Int(0,AnimSize);

				Commands->Set_Animation(sender,CTFAnimations[Animation2Play],false,0,0.0f,-1.0f,false);
				
				if (Data->CTFCaps[Team] >= Settings->CTFCapLimit) {
					BaseControllerClass::Find_Base(OtherTeam)->Destroy_Base();
				}
				else {
					Create_CTF_PedFlag(OtherTeam);
				}
			}
		}
	}
}

//Attached to the flag when it's on the ground.
void MDB_SSGM_CTF_DropFlag::Created(GameObject *obj) {
	PickedUp = false;
	int Team = Get_Object_Type(obj);
	if (Settings->CTFFriendlyFlagRadar) {
		GameObject *AttachedFlag = Commands->Create_Object_At_Bone(obj,Settings->CTFFlagBackPreset.c_str(),"Origin");
		Commands->Attach_To_Object_Bone(AttachedFlag, obj,"Origin");
		Commands->Disable_All_Collisions(AttachedFlag);
		Commands->Set_Player_Type(AttachedFlag,Team);
		Commands->Set_Model(AttachedFlag,"null");
		Data->CTFFlagAttached[Team][0] = Commands->Get_ID(AttachedFlag);
	}	
	if (Settings->CTFEnemyFlagRadar) {
		GameObject *AttachedFlag2 = Commands->Create_Object_At_Bone(obj,"Invisible_Object","Origin");
		Commands->Attach_To_Object_Bone(AttachedFlag2, obj, "Origin");
		Commands->Disable_All_Collisions(AttachedFlag2);
		Commands->Set_Player_Type(AttachedFlag2,PTTEAM(Team));
		Commands->Set_Model(AttachedFlag2,"null");
		Set_Obj_Radar_Blip_Shape(AttachedFlag2,BLIP_SHAPE_OBJECTIVE);
		Set_Obj_Radar_Blip_Color(AttachedFlag2,Team);
		Data->CTFFlagAttached[Team][1] = Commands->Get_ID(AttachedFlag2);
	}
	if (Settings->CTFReturnTime > 0.0f) {
		Commands->Start_Timer(obj,this,Settings->CTFReturnTime,1);
	}
	Set_Is_Powerup_Persistant(obj,true); //Makes it so the powerup doesn't disappear when a player picks it up, allowing the script to destroy it when appropriate
	Set_Powerup_Always_Allow_Grant(obj,true); //Make it so the powerup can always be picked up
	Set_Powerup_Grant_Sound(obj,0); //The grant sound fucks up when a friendly player stands on top of their own flag
}

void MDB_SSGM_CTF_DropFlag::Custom(GameObject *obj, int message, int param, GameObject *sender) {
	if (message == CUSTOM_EVENT_POWERUP && !PickedUp && Commands->Get_Health(sender) > 0.0f) {
		int Team = Get_Object_Type(obj);
		PickedUp = true;
		if (Team != Get_Object_Type(sender)) { //Enemy picked up flag
			Commands->Attach_Script(sender,"MDB_SSGM_CTF_FlagHolder","");

			Data->CTFFlagHolder[Team] = Commands->Get_ID(sender);	
			CTF_Message(3,Team,sender,0);
			Set_Flag_Location(Team,2);
		
			Commands->Destroy_Object(obj);
		}
		else { //Friendly picked up flag
			Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][0]));
			Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][1]));

			Create_CTF_PedFlag(Team);
			CTF_Message(4,Team,sender,0);

			Commands->Destroy_Object(obj);
		}
	}
}

void MDB_SSGM_CTF_DropFlag::Timer_Expired(GameObject *obj, int number) {
	Commands->Destroy_Object(obj);
}

void MDB_SSGM_CTF_DropFlag::Destroyed(GameObject *obj) {
	//Either the return timer expired or the flag fell into blue hell.
	if (!PickedUp) {
		int Team = Get_Object_Type(obj);
		Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][0]));
		Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][1]));
		Create_CTF_PedFlag(Team);
		CTF_Message(5,Team,0,0);
	}
}

//Attached to the player carrying the flag.
void MDB_SSGM_CTF_FlagHolder::Created(GameObject *obj) {
	Dropped = false;
	int Team = PTTEAM(Get_Object_Type(obj));

	Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][0]));
	Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][1]));
	GameObject *AttachedFlag = Commands->Create_Object_At_Bone(obj,Settings->CTFFlagBackPreset.c_str(),"bone for bag");
	Commands->Attach_To_Object_Bone(AttachedFlag,obj,"bone for bag");
	Commands->Disable_All_Collisions(AttachedFlag);
	if (Settings->CTFFriendlyFlagRadar) {
		Commands->Set_Player_Type(AttachedFlag,Team);
	}
	else {
		Commands->Set_Player_Type(AttachedFlag,-2);
	}
	Commands->Set_Model(AttachedFlag,Settings->CTFFlagModel[Team].c_str());
	Data->CTFFlagAttached[Team][0] = Commands->Get_ID(AttachedFlag);
	if (Settings->CTFEnemyFlagRadar) {
		GameObject *AttachedFlag2 = Commands->Create_Object_At_Bone(obj,"Invisible_Object","bone for bag");
		Commands->Attach_To_Object_Bone(AttachedFlag2,obj,"bone for bag");
		Commands->Disable_All_Collisions(AttachedFlag2);
		Commands->Set_Player_Type(AttachedFlag2,Get_Object_Type(obj));
		Commands->Set_Model(AttachedFlag2,"null");
		Set_Obj_Radar_Blip_Shape(AttachedFlag2,BLIP_SHAPE_OBJECTIVE);
		Set_Obj_Radar_Blip_Color(AttachedFlag2,Team);
		Data->CTFFlagAttached[Team][1] = Commands->Get_ID(AttachedFlag2);
	}

	if (Settings->CTFRegenForHolder) {
		Commands->Start_Timer(obj,this,1.0f,1);
	}
	if (Is_Stealth(obj)) {
		Commands->Start_Timer(obj,this,1.0f,2);
	}
}

void MDB_SSGM_CTF_FlagHolder::Timer_Expired(GameObject *obj, int number) {
	if (number == 1 && Commands->Get_Health(obj) > 0.0f) {
		Commands->Apply_Damage(obj,(Settings->CTFRegenAmount * -1.0f),"Repair",0);
		Commands->Start_Timer(obj,this,1.0f,1);
	}
	else if (number == 2) {
		Commands->Apply_Damage(obj,0,"Harmless",false);
		Commands->Start_Timer(obj,this,1.0f,2);
	}
}

void MDB_SSGM_CTF_FlagHolder::Killed(GameObject *obj, GameObject *shooter) {
	if (!Dropped) {
		Dropped = true;
		int Team = PTTEAM(Get_Object_Type(obj));
		Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][0]));
		Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][1]));
		Create_CTF_DropFlag(Team,Commands->Get_Position(obj));
		CTF_Message(2,Team,obj,shooter);
	}
}

void MDB_SSGM_CTF_FlagHolder::Destroyed(GameObject *obj) {
	if (!Dropped) {
		Dropped = true;
		int Team = PTTEAM(Get_Object_Type(obj));
		Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][0]));
		Commands->Destroy_Object(Commands->Find_Object(Data->CTFFlagAttached[Team][1]));
		Create_CTF_DropFlag(Team,Commands->Get_Position(obj));
		CTF_Message(2,Team,obj,0);
	}
}

void MDB_SSGM_CTF_FlagHolder::Custom(GameObject *obj, int message, int param, GameObject *sender) {
	if (message == 294829) {
		Dropped = true;
		Destroy_Script();
	}
}

//Announces the capture limit and class.
void MDB_SSGM_CTF_Announcement::NewCreated(GameObject *obj) {
	CTFController = obj;
	Commands->Start_Timer(obj,this,30.0f,1);
	Commands->Start_Timer(obj,this,90.0f,1);
}

void MDB_SSGM_CTF_Announcement::Timer_Expired(GameObject *obj, int number) {
	Console_Input(StrFormat("msg Running in Capture The Flag mode. This rounds CTF class will be '%s' with a capture limit of %d.",Settings->CTFClassName.c_str(),Settings->CTFCapLimit).c_str());
	if (Settings->CTFReverse) {
		Console_Input("msg This is a Reverse CTF game. Your objective is to take the enemy flag from your base and run it to your pedestal in the enemy base.");
		Console_Input("msg Keep in mind that returning your own flag is not always the best course of action!");
	}
}

void MDB_SSGM_CTF_Announcement::Custom(GameObject *obj, int message, int param, GameObject *sender) {
	if (message == 983294) {
		GameObject *Player = Get_GameObj(param);
		GameObject *Flag0 = Commands->Find_Object(Data->CTFFlagAttached[0][1]);
		if (Flag0) {
			Set_Obj_Radar_Blip_Shape_Player(Player,Flag0,BLIP_SHAPE_OBJECTIVE);
			Set_Obj_Radar_Blip_Color_Player(Player,Flag0,BLIP_COLOR_RED);
		}
		GameObject *Flag1 = Commands->Find_Object(Data->CTFFlagAttached[1][1]);
		if (Flag1) {
			Set_Obj_Radar_Blip_Shape_Player(Player,Flag1,BLIP_SHAPE_OBJECTIVE);
			Set_Obj_Radar_Blip_Color_Player(Player,Flag1,BLIP_COLOR_GOLD);
		}
	}
}


/* ************************************************************************************************************* */

ScriptRegistrant<MDB_SSGM_CTF_Flag> MDB_SSGM_CTF_Flag_Registrant("MDB_SSGM_CTF_Flag","");
ScriptRegistrant<MDB_SSGM_CTF_DropFlag> MDB_SSGM_CTF_DropFlag_Registrant("MDB_SSGM_CTF_DropFlag","");
ScriptRegistrant<MDB_SSGM_CTF_FlagHolder> MDB_SSGM_CTF_FlagHolder_Registrant("MDB_SSGM_CTF_FlagHolder","");
ScriptRegistrant<MDB_SSGM_CTF_Announcement> MDB_SSGM_CTF_Announcement_Registrant("MDB_SSGM_CTF_Announcement","");
